import React, { useContext } from "react";
import { AuthFormType, UserType, AuthContextType } from "types";
import { useMount, useAsync } from "hooks";
import * as auth from "auth-provider";
import { server } from "server";
import { FullPageLoading, FullPageErrorFallback } from "components/lib";
import { useQueryClient } from "react-query";

const AuthContext = React.createContext<AuthContextType | undefined>(undefined);
AuthContext.displayName = "AuthContext";

const bootstrapUser = async () => {
  const token = auth.getToken();
  if (!token) return null;

  const result = await server("me", { token });
  return result?.user as UserType;
};

export const Provider: React.FC = ({ children }) => {
  const {
    run,
    data: user,
    setDate: setUser,
    error,
    isLoading,
    isError,
    isIdle,
  } = useAsync<UserType | null>();
  const queryClient = useQueryClient();

  const login = (form: AuthFormType) => {
    return auth.login(form).then(setUser);
  };

  const register = (form: AuthFormType) => {
    return auth.register(form).then(setUser);
  };

  const logout = () => {
    return auth.logout().then(() => {
      setUser(null);
      queryClient.clear();
    });
  };

  useMount(() => {
    run(bootstrapUser());
  });

  if (isIdle || isLoading) {
    return <FullPageLoading />;
  }

  if (isError) {
    return <FullPageErrorFallback error={error} />;
  }

  const value = { user, login, register, logout };

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};

export const useAuth = () => {
  const context = useContext(AuthContext);

  if (!context) {
    throw new Error("userAuth必须AuthProvider中使用");
  }

  return context;
};
